package pers.cj.pdos.controller;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import pers.cj.pdos.constant.OrderType;
import pers.cj.pdos.controller.base.BaseController;

import pers.cj.pdos.controller.entity.ResponseData;
import pers.cj.pdos.controller.entity.ResponseEntity;
import pers.cj.pdos.controller.entity.ResponseList;
import pers.cj.pdos.entity.*;
import pers.cj.pdos.service.*;
import pers.cj.pdos.utils.*;
import pers.cj.pdos.vo.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

@Controller
@RequestMapping("/sale")
public class RetailController extends BaseController {
    @Autowired
    IRetailSetService retailSetService;
    @Autowired
    IUserService userService;
    @Autowired
    IOrderRuleService orderRuleService;
    @Autowired
    ISaleService saleService;
    @Autowired
    IUserHangService userHangService;

    @RequiresPermissions("retail:order")
    @RequestMapping("/retail")
    public String retail(Model model){
        model.addAttribute(getCompany());
        UserVo userVo = getLoginUserVo();
        model.addAttribute(userVo);
        RetailSetVo retailSet = retailSetService.getVoByStore(userVo.getStoreId());
        if (retailSet == null) {
            model.addAttribute("noSet","1");
        } else {
            model.addAttribute(retailSet);
        }


        Boolean exist = userHangService.checkHangExistByUserId(userVo.getId());
        model.addAttribute("exist",exist);
        return "/retail/retail";
    }

    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/hotKeyHelp")
    public String hotKeyHelp(){
        return "/retail/hotKeyHelp";
    }

    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/hang")
    public String hang(Model model){
        String userId = getLoginUserId();
        Boolean exist = userHangService.checkHangExistByUserId(userId);
        model.addAttribute("exist",exist);
        model.addAttribute("userId",userId);
        return "/retail/hang";
    }

    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/take")
    public String take(){
        return "/retail/take";
    }


    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/lock")
    public String lock(){
        return "/retail/lock";
    }


    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/noSetTip")
    public String noSetTip(){
        return "/retail/noSetTip";
    }


    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/sett")
    public String sett(Model model){
        RetailSetVo retailSet = retailSetService.getVoByStore(getLoginUserVo().getStoreId());
        if (retailSet != null) {
            model.addAttribute(retailSet);
        }
        return "/retail/sett";
    }


    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/selectGoods")
    public String selectGoods(Model model,String houseId,String search){
        model.addAttribute("houseId",houseId);
        model.addAttribute("search",search);
        return "/retail/selectGoods";
    }


    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/selectCustom")
    public String selectCustom(Model model,String search){
        model.addAttribute("search",search);
        return "/retail/selectCustom";
    }


    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/selectSn")
    public String selectSn(Model model,String houseId,String goodsId){
        model.addAttribute("houseId",houseId);
        model.addAttribute("goodsId",goodsId);
        return "/retail/selectSn";
    }

    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/changeGoods")
    public String changeGoods(Model model,String houseId,String goodsId){
        model.addAttribute("houseId",houseId);
        model.addAttribute("goodsId",goodsId);
        return "/retail/changeGoods";
    }

    @ResponseBody
    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/getRetailGoodsVoList")
    public ResponseList getRetailGoodsVoList(int page, int limit, String houseId, String search){
        if (Utils.isEmpty(houseId)) {
            return ResponseList.fail("仓库不能为空");
        }
        Company company = getCompany();
        List<RetailGoodsVo> list = retailSetService.listRetailGoodsVo(page,limit,company.getId(),houseId, Utils.genLikeData(search));
        long count = retailSetService.countRetailGoods(company.getId(),houseId, Utils.genLikeData(search));
        return ResponseList.success(count,list);
    }

    @ResponseBody
    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/lockRetail")
    public ResponseEntity lockRetail(){
        User user = new User();
        user.setId(getLoginUserId());
        user.setRetailStatus(2);
        userService.updateById(user);
        return ResponseEntity.success();
    }

    @ResponseBody
    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/unLockRetail")
    public ResponseEntity unLockRetail(@RequestBody PasswordVo passwordVo){
        if (Utils.isEmpty(passwordVo.getPassword())) {
            return ResponseEntity.fail("密码不能为空");
        }
        User user = getLoginUserVo();
        String passwordMd5 = MD5Utils.md5(passwordVo.getPassword(),1,user.getSalt());
        if (!user.getPassword().equals(passwordMd5)) {
            return ResponseEntity.fail("密码错误");
        }

        User temp = new User();
        temp.setId(user.getId());
        temp.setRetailStatus(1);
        userService.updateById(temp);
        return ResponseEntity.success();
    }


    @ResponseBody
    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/addSale")
    public ResponseEntity add(@RequestBody SaleVo saleVo){
        Company company = getCompany();

        if (Utils.isEmpty(saleVo.getSaleGoodsVoList()) && Utils.isEmpty(saleVo.getSalePacketVoList())){
            return ResponseEntity.fail("您未选择任何商品");
        }



        if (saleService.checkNo(saleVo.getNo(),company.getId())){
            return ResponseEntity.fail("编号已被使用");
        }

        if (getHouseLocking(saleVo.getHouseId())) {
            return ResponseEntity.fail("仓库被锁定，暂时不能进行零售收银");
        }



        GoodsUtil goodsUtil = new GoodsUtil(saleVo.getHouseId(),saleVo.getSaleGoodsVoList(),saleVo.getSalePacketVoList());
        String msg = goodsUtil.checkStock();
        if (msg!=null){
            return ResponseEntity.fail(msg);
        }



        Sale sale = DataUtil.genEntityFromVo(Sale.class, saleVo);
        DataUtil.processEntity(company,sale);
        OrderRule orderRule = orderRuleService.getByType(company.getId(), OrderType.XSD.getType());
        sale.setNo(PdosUtils.getNo(orderRule));
        sale.setRetail(true);
        sale.setStatus(1);
        sale.setRefund(0);
        sale.setType(2);
        sale.setTicket(1);
        sale.setDelivery(false);
        sale.setDeliveryDate(null);
        sale.setContacts("");
        sale.setPhone("");
        sale.setAddress("");
        sale.setUserId(getLoginUserId());
        sale.setDate(new Date());
        sale.setMakeUserId(getLoginUserId());
        sale.setMakeTime(new Date());
        sale.setClose(false);
        sale.setTax(new BigDecimal(0));
        sale.setOtherAmt(new BigDecimal(0));
        sale.setRealAmt(sale.getTotalAmt());

        sale.setSaleOrderId(null);

        BigDecimal totalAmount = goodsUtil.getTotalAmount();
        if (sale.getDiscountFlag() == 1) {
            sale.setAfterDiscountAmt(totalAmount.multiply(sale.getDiscountRate()).divide(new BigDecimal(100)));
            sale.setDiscountAmt(totalAmount.subtract(sale.getAfterDiscountAmt())); //折扣金额 = 总金额- 折后金额
        } else {
            sale.setAfterDiscountAmt(totalAmount.subtract(sale.getDiscountAmt()));
            sale.setDiscountRate(new BigDecimal(100).multiply(sale.getAfterDiscountAmt()).divide(totalAmount,4, RoundingMode.HALF_UP)); //折扣率 = 100*折后金额 / 总金额
        }
        sale.setTax(new BigDecimal(0));


        Map<String,BigDecimal> costMap = genCostMap(goodsUtil);


        BigDecimal profits = new BigDecimal(0);//销售单的毛利

        List<SaleGoods> saleGoodsList = new ArrayList<>();
        List<GoodsSn> goodsSnList = new ArrayList<>();
        List<GoodsSnLog> goodsSnLogList = new ArrayList<>();

        if (!Utils.isEmpty(saleVo.getSaleGoodsVoList())) {
            for (SaleGoodsVo vo : saleVo.getSaleGoodsVoList()) {
                SaleGoods entity = DataUtil.genEntityFromVo(SaleGoods.class, vo);
                DataUtil.processEntity(company, entity);
                entity.setSaleId(sale.getId());
                entity.setRefundNumber(new BigDecimal(0));

                BigDecimal cost = costMap.containsKey(entity.getGoodsId()) ? costMap.get(entity.getGoodsId()) : new BigDecimal(0);
                cost = cost.multiply(entity.getNumber()).multiply(entity.getTimes());//该商品的成本

                entity.setAfterDiscountAmt(entity.getAmount().multiply(sale.getDiscountRate()).divide(new BigDecimal(100)));//折后金额 = 金额 * 折扣率 / 100
                entity.setProfits(entity.getAfterDiscountAmt().subtract(cost));//该商品的毛利 = 折后的商品金额-成本
                entity.setTax(new BigDecimal(0));

                profits = profits.add(entity.getProfits());

                saleGoodsList.add(entity);

                if (!Utils.isEmpty(vo.getGoodsSnList())) {
                    for (GoodsSn goodsSn : vo.getGoodsSnList()) {
                        goodsSnList.add(goodsSn);

                        GoodsSnLog log = new GoodsSnLog();
                        DataUtil.processEntity(company, log);
                        log.setGoodsId(goodsSn.getGoodsId());
                        log.setSn(goodsSn.getSn());
                        log.setType(2);
                        log.setSaleGoodsId(entity.getId());
                        if (!Utils.isEmpty(sale.getBorrowOutId())) {
                            log.setBorrow(1);
                        }
                        goodsSnLogList.add(log);
                    }
                }
            }
        }

        List<SalePacket> salePacketList = new ArrayList<>();
        List<SalePacketGoods> salePacketGoodsList = new ArrayList<>();

        if (!Utils.isEmpty(saleVo.getSalePacketVoList())) {
            for (SalePacketVo vo : saleVo.getSalePacketVoList()) {
                SalePacket entity = DataUtil.genEntityFromVo(SalePacket.class, vo);
                DataUtil.processEntity(company, entity);
                entity.setSaleId(sale.getId());
                entity.setRefundNumber(new BigDecimal(0));
                entity.setAfterDiscountAmt(entity.getAmount().multiply(sale.getDiscountRate()).divide(new BigDecimal(100)));//折后金额 = 金额 * 折扣率 / 100
                entity.setTax(new BigDecimal(0));
                BigDecimal price = entity.getAfterDiscountAmt().divide(entity.getNumber(),4, RoundingMode.HALF_UP); // 折后套餐价

                BigDecimal packet_profits = new BigDecimal(0);//套餐的毛利
                BigDecimal packetGoodsTotal = genPacketTotal(vo);//此套餐的总价，用于下面计算实际金额
                for (SalePacketGoodsVo pgv : vo.getPacketGoodsVoList()) {
                    SalePacketGoods pg = DataUtil.genEntityFromVo(SalePacketGoods.class, pgv);
                    DataUtil.processEntity(company, pg);
                    pg.setSaleId(entity.getSaleId());
                    pg.setSalePacketId(entity.getId());
                    pg.setAfterDiscountAmt(price.multiply(pg.getAmount()).divide(packetGoodsTotal,4, RoundingMode.HALF_UP));//套餐中商品的实际金额（折后换算的金额）
                    pg.setTax(new BigDecimal(0));

                    BigDecimal cost = costMap.containsKey(pg.getGoodsId()) ? costMap.get(pg.getGoodsId()) : new BigDecimal(0);
                    cost = cost.multiply(pg.getNumber()).multiply(pg.getTimes());//该商品的成本
                    pg.setProfits(pg.getAfterDiscountAmt().subtract(cost));//该商品的毛利 = 折后的商品金额-成本

                    packet_profits = packet_profits.add(pg.getProfits());

                    salePacketGoodsList.add(pg);
                }

                entity.setProfits(packet_profits.multiply(entity.getNumber()));//套餐的总利润，数量*单个套餐利润
                profits = entity.getProfits().add(profits);
                salePacketList.add(entity);
            }
        }

        sale.setProfits(profits);

        saleService.retailInsert(sale, saleGoodsList,goodsSnList,goodsSnLogList, salePacketList, salePacketGoodsList);
        return ResponseEntity.success();
    }

    /**
     * 当前登录用户的上一笔零售销售单
     * @return
     */
    @ResponseBody
    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/getLastOrder")
    public ResponseData getLastOrder(){
        String userId = getLoginUserId();
        SaleVo saleVo = saleService.getLastRetailByUserId(userId);
        if (saleVo == null) {
            return ResponseData.fail("无上一单数据");
        }
        return ResponseData.success(saleVo);
    }

    /**
     * 挂单
     * @return
     */
    @ResponseBody
    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/hangGoods")
    public ResponseEntity hangGoods(@RequestBody UserHangVo userHangVo){

        if (Utils.isEmpty(userHangVo.getUserHangGoodsList())){
            return ResponseEntity.fail("商品不能为空");
        }

        processHang(userHangVo);
        return ResponseEntity.success();
    }

    /**
     * 取单
     * @return
     */
    @ResponseBody
    @RequiresPermissions("retail:order")
    @RequestMapping("/retail/takeGoods")
    public ResponseData takeGoods(@RequestBody UserHangVo userHangVo){
        RetailSetVo retailSet = retailSetService.getVoByStore(getLoginUserVo().getStoreId());
        if (retailSet == null) {
            return ResponseData.fail("请联系管理员，该门店的零售收银参数已被删除");
        }

        String userId = getLoginUserId();
        //1.取挂单
        UserHangVo db = userHangService.getVoByUserId(userId,retailSet.getHouseId());
        if (db == null) {
            return  ResponseData.fail("您还没有挂单");
        }

        //成功取到挂单后，如果入参中含有挂单商品表，则表示还要新增挂单
        if (!Utils.isEmpty(userHangVo.getUserHangGoodsList())) {
            processHang(userHangVo);
        } else {
            //直接取单的话，则要删除原挂单
            userHangService.deleteByUserId(userId);
        }

        //将取到的挂单返回给前端
        return ResponseData.success(db);
    }

    private void processHang(UserHangVo userHangVo) {
        Company company = getCompany();
        UserHang userHang = DataUtil.genEntityFromVo(UserHang.class, userHangVo);
        List<UserHangGoods> userHangGoodsList = userHangVo.getUserHangGoodsList();
        List<UserHangSn> userHangSnList = userHangVo.getUserHangSnList();
        Map<String,Object> map = new HashMap<>();
        map.put("userId",getLoginUserId());
        DataUtil.processEntity(company,userHang,map);
        map.put("userHangId",userHang.getId());
        DataUtil.processList(company,userHangGoodsList,map);

        if (!Utils.isEmpty(userHangSnList)) {
            DataUtil.processList(company,userHangSnList,map);
        }

        userHangService.insert(userHang, userHangGoodsList,userHangSnList);
    }

    private BigDecimal genPacketTotal(SalePacketVo vo){
        BigDecimal total = new BigDecimal(0);

        for (SalePacketGoodsVo pgv:vo.getPacketGoodsVoList()) {
            total = total.add(pgv.getAmount());
        }

        return total;
    }
}
